Accelerate IDE PIO on HVM/IA64 [3/3]
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 27 Feb 2007 15:34:55 +0000 (15:34 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 27 Feb 2007 15:34:55 +0000 (15:34 +0000)
Add a bufferring mechanism for IDE PIO in a hypervisor.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
xen/arch/ia64/vmx/mmio.c
xen/arch/ia64/vmx/vmx_init.c
xen/include/asm-ia64/vmx_platform.h
xen/include/public/arch-ia64.h

index 08247e1c1485c181c7ad2a39eff15f689b835ad6..682d9877f212ab89a766c5b48d92e55869db79c8 100644 (file)
@@ -136,6 +136,56 @@ static void low_mmio_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
     }
     return;
 }
+
+int vmx_ide_pio_intercept(ioreq_t *p, u64 *val)
+{
+    struct buffered_piopage *pio_page =
+        (void *)(current->domain->arch.hvm_domain.buffered_pio_va);
+    struct pio_buffer *piobuf;
+    uint32_t pointer, page_offset;
+
+    if (p->addr == 0x1F0)
+       piobuf = &pio_page->pio[PIO_BUFFER_IDE_PRIMARY];
+    else if (p->addr == 0x170)
+       piobuf = &pio_page->pio[PIO_BUFFER_IDE_SECONDARY];
+    else
+       return 0;
+
+    if (p->size != 2 && p->size != 4)
+        return 0;
+
+    pointer = piobuf->pointer;
+    page_offset = piobuf->page_offset;
+
+    /* sanity check */
+    if (page_offset + pointer < offsetof(struct buffered_piopage, buffer))
+       return 0;
+    if (page_offset + piobuf->data_end > PAGE_SIZE)
+       return 0;
+
+    if (pointer + p->size < piobuf->data_end) {
+        uint8_t *bufp = (uint8_t *)pio_page + page_offset + pointer;
+        if (p->dir == IOREQ_WRITE) {
+            if (likely(p->size == 4 && (((long)bufp & 3) == 0)))
+                *(uint32_t *)bufp = *val;
+            else
+                memcpy(bufp, val, p->size);
+        } else {
+            if (likely(p->size == 4 && (((long)bufp & 3) == 0))) {
+                *val = *(uint32_t *)bufp;
+            } else {
+                *val = 0;
+                memcpy(val, bufp, p->size);
+            }
+        }
+        piobuf->pointer += p->size;
+        p->state = STATE_IORESP_READY;
+        vmx_io_assist(current);
+        return 1;
+    }
+    return 0;
+}
+
 #define TO_LEGACY_IO(pa)  (((pa)>>12<<2)|((pa)&0x3))
 
 static void legacy_io_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
@@ -161,6 +211,9 @@ static void legacy_io_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
 
     p->io_count++;
 
+    if (vmx_ide_pio_intercept(p, val))
+        return;
+
     vmx_send_assist_req(v);
     if(dir==IOREQ_READ){ //read
         *val=p->data;
index f2548322b2c89f37bccbe5926deb1d2f4dff1476..10daa5c42466438da6f9faf45cc3bd1d9833711d 100644 (file)
@@ -390,6 +390,8 @@ void vmx_setup_platform(struct domain *d)
        spin_lock_init(&d->arch.hvm_domain.buffered_io_lock);
        d->arch.hvm_domain.buffered_io_va =
                (unsigned long)__va(__gpa_to_mpa(d, BUFFER_IO_PAGE_START));
+       d->arch.hvm_domain.buffered_pio_va =
+               (unsigned long)__va(__gpa_to_mpa(d, BUFFER_PIO_PAGE_START));
        /* TEMP */
        d->arch.vmx_platform.pib_base = 0xfee00000UL;
 
index 5c0bd4c595ecbf908d2434a7f249fc20c02d97e9..87160b10cf6d2627cdd4fbcd6c467d4573a67dbc 100644 (file)
@@ -24,8 +24,9 @@
 #include <asm/viosapic.h>
 struct mmio_list;
 typedef struct virtual_platform_def {
-    unsigned long          buffered_io_va;
-    spinlock_t             buffered_io_lock;
+    unsigned long       buffered_io_va;
+    spinlock_t          buffered_io_lock;
+    unsigned long       buffered_pio_va;
     unsigned long       shared_page_va;
     unsigned long       pib_base;
     unsigned long       params[HVM_NR_PARAMS];
index 8c6aaed3569d0e87824d30060b8c8c1458f5e197..ef9e254cd226125b5c080524f1a06293dcc122f7 100644 (file)
@@ -91,11 +91,14 @@ typedef unsigned long xen_ulong_t;
 #define IO_PAGE_SIZE  PAGE_SIZE
 
 #define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE)
-#define STORE_PAGE_SIZE         PAGE_SIZE
+#define STORE_PAGE_SIZE  PAGE_SIZE
 
-#define BUFFER_IO_PAGE_START (STORE_PAGE_START+PAGE_SIZE)
+#define BUFFER_IO_PAGE_START (STORE_PAGE_START+STORE_PAGE_SIZE)
 #define BUFFER_IO_PAGE_SIZE PAGE_SIZE
 
+#define BUFFER_PIO_PAGE_START (BUFFER_IO_PAGE_START+BUFFER_IO_PAGE_SIZE)
+#define BUFFER_PIO_PAGE_SIZE PAGE_SIZE
+
 #define IO_SAPIC_START   0xfec00000UL
 #define IO_SAPIC_SIZE    0x100000